/**
 * MIT License
 *
 * Copyright (c) 2024 小村程序员
 * Email: 397237738@qq.com
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.open.cobertura.core.util;


import org.objectweb.asm.Label;
import org.open.cobertura.core.model.InstructionStateful;
import org.open.cobertura.core.model.LabelStateful;

import java.io.OutputStreamWriter;

public class CoberturaLabelStatefulUtil {
    /**
     * 设置label的状态为单一跳转状态
     * @param label
     */
    public static void setLabelStateForIsJump(final Label label,int lineNumber){
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }else{
            labelStateful=new LabelStateful();
            label.info=labelStateful;

        }
        labelStateful.lineNumber=lineNumber;
        if(labelStateful.isJump || labelStateful.isNext){
            labelStateful.isMultiJump=true;
        }else{
            labelStateful.isJump=true;
        }
    }

    public static void setLabelStateForIsMultiJump(final Label label,int lineNumber){
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }else{
            labelStateful=new LabelStateful();
            label.info=labelStateful;
        }
        labelStateful.lineNumber=lineNumber;
        labelStateful.isNext=true;
        if(labelStateful.isJump){
            labelStateful.isMultiJump=true;
        }
    }

    /**
     * 判断是否存在多目标的指令
     * @param label
     * @return
     */
    public static boolean isLabelStateForIsMultiJump(final Label label){
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }
        if(labelStateful==null){
            return false;
        }
        return labelStateful.isMultiJump;
    }

    /**
     * 设置是否是方法的入口
     * @param label
     */
    public static void setMethodBeginLine(final Label label,int lineNumber) {
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }else{
            labelStateful=new LabelStateful();
            label.info=labelStateful;
        }
        labelStateful.methodBeginLine = true;
        labelStateful.lineNumber=lineNumber;
    }

    /**
     * 是否需要进行插桩
     * @param label
     */
    public static boolean isNeedProbe(final Label label){
        if(label.info!=null){
            LabelStateful labelStateful=(LabelStateful)label.info;
            if(labelStateful.isNext && (labelStateful.isMultiJump || labelStateful.methodBeginLine)){
                return true;
            }
        }
        return false;
    }

    /**
     * 判断该标签是否有潜在的指令，也就是指令是否是连续的
     * @param label
     * @return
     */
    public static boolean isNext(final Label label){
        if(label.info!=null) {
            LabelStateful labelStateful = (LabelStateful) label.info;
            if(labelStateful.isNext) {
                return true;
            }
        }
        return false;
    }
    /**
     * 给label标签设定指令集
     * @param label
     * @param instructionStateful
     */
    public static void setInstruction(final Label label, final InstructionStateful instructionStateful){
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }else{
            labelStateful=new LabelStateful();
            label.info=labelStateful;
        }
        labelStateful.instructionStateful=instructionStateful;
    }

    /**
     * 得到标签上的指令
     * @param label
     * @return
     */
    public static InstructionStateful getInstruction(final Label label){
        LabelStateful labelStateful=null;
        if(label.info instanceof LabelStateful){
            labelStateful=(LabelStateful) label.info;
        }
        if(labelStateful!=null){
            return labelStateful.instructionStateful;
        }
        return null;
    }
}
